"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 故障&可靠性测试
Case Name   : 持续插入大量数据，延迟小于同步所需时间
Create At   : 2021/03/03
@zou_jialiang0505328126
Description :
    1.设置延迟为1
    2.切换备节点为级联备
    3.执行tpcc
    4.等待主备一致
    5.查询各节点
    6.重复执行3~5 20次
Expect      :
    1.设置成功
    2.切换成功
    3.执行tpcc成功
    4.主备同步
    5.数据一致
    6.通过率100%
History     :
    modified by @wan005 at 2022.09.23:优化用例关闭autovacuum,确保级联备查询一致,再观察
"""

import unittest
import os
import time
from yat.test import Node
from yat.test import macro
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger


class RecoveryDelay(unittest.TestCase):
    commonshpri = CommonSH('PrimaryDbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('----Opengauss_Reliability_Dbsys_Case258.py 开始执行------')
        self.db_primary_root_node = Node(node='PrimaryRoot')
        self.db_standby_node =  \
            [Node(node='Standby1Root'), Node(node='Standby2Root')]
        self.db_standby_user_node =  \
            [Node(node='Standby1DbUser'), Node(node='Standby2DbUser')]
        self.db_primary_user_node = Node(node='PrimaryDbUser')
        self.comshsta = \
            [CommonSH('Standby1DbUser'), CommonSH('Standby2DbUser')]
        self.constant = Constant()
        self.com_pri = Common('PrimaryRoot')
        self.com_sta = [Common('Standby1Root'), Common('Standby2Root')]

        self.log.info('=====安装ntp服务=======')
        install_cmd = "yum install -y ntp && " \
                      "systemctl enable ntpd && systemctl start ntpd"
        for i in range(2):
            result = self.db_standby_node[i].sh(install_cmd).result()
            self.log.info(result)

        self.log.info('------同步集群时间--------')
        for i in range(2):
            current = self.db_primary_root_node.sh(
                "date \"+%m/%d/%Y %H:%M:%S\"").result()
            self.log.info(current)
            datecmd = f'date -s "{current}";hwclock --systohc;' \
                f'service ntpd stop;ntpdate ntp.api.bz;service ntpd start'
            self.log.info(datecmd)
            result = self.db_standby_node[i].sh(datecmd).result()
            self.log.info(result)

        self.log.info('------备份postgres.conf文件----------')
        self.conf_path = os.path.join(
            macro.DB_INSTANCE_PATH, macro.DB_PG_CONFIG_NAME)
        shell_cmd = f"cp {self.conf_path} {self.conf_path}_testbak"
        self.log.info(shell_cmd)
        result = self.db_primary_user_node.sh(shell_cmd).result()
        self.log.info(result)

    def test_recoverydelay(self):
        self.log.info('-----设置recovery_min_apply_delay=1----')
        result = self.commonshpri.executeGsguc(
            'reload', self.constant.GSGUC_SUCCESS_MSG,
            'recovery_min_apply_delay=1')
        self.assertTrue(result)

        self.log.info('-----设置autovacuum=off----')
        result = self.commonshpri.executeGsguc(
            'reload', self.constant.GSGUC_SUCCESS_MSG,
            'autovacuum=off')
        self.assertTrue(result)

        self.log.info('-----设置ha_module_debug=on----')
        result = self.commonshpri.executeGsguc(
            'reload', self.constant.GSGUC_SUCCESS_MSG,
            'ha_module_debug=on')
        self.assertTrue(result)

        self.log.info('-------将备节点切换为级联备---------')
        result = self.comshsta[0].buildStandby('-M cascade_standby')
        self.assertIn(self.constant.REBUILD_SUCCESS_MSG, result)
        result = self.comshsta[0].exec_refresh_conf()
        self.assertTrue(result)

        self.log.info('--------等待主备一致------------')
        result = self.comshsta[1].check_data_consistency()
        self.assertTrue(result)
        for i in range(90):
            result = self.commonshpri.check_cascade_standby_consistency()
            if result:
                break
            time.sleep(20)
        self.assertTrue(result)

        for i in range(20):
            self.log.info('-----------------执行TPCC-------------')
            result = self.com_pri.startTPCC(self.db_primary_root_node,
                                            macro.TPCC_PATH)
            self.log.info(result)
            self.assertIn(self.constant.TPCC_SUCCESS_MSG, result)

            self.log.info('--------等待主备一致------------')
            result = self.comshsta[1].check_data_consistency()
            self.assertTrue(result)
            for j in range(90):
                result = self.commonshpri.check_cascade_standby_consistency()
                if result:
                    break
                time.sleep(20)
            self.assertTrue(result)

            self.log.info('-----检查数据一致性----')
            nodes_tuple = (self.db_primary_user_node,
                           self.db_standby_user_node[0],
                           self.db_standby_user_node[1])
            flag = self.com_pri.check_data_sample_by_all(r'\d', *nodes_tuple)
            self.assertTrue(flag)

            table_dict = self.com_pri.format_sql_result(
                self.commonshpri.executDbSql(r'\d'))
            table_name = table_dict.get('Name')
            for name in table_name:
                select_sql = f'select count(*) from {name};'
                flag = self.com_pri.check_data_sample_by_all(select_sql,
                                                            *nodes_tuple)
                self.assertTrue(flag)

    def tearDown(self):
        self.log.info('-----------------------------环境清理--------------------')
        self.log.info('--------------还原配置文件-------------')
        shell_cmd = f"rm -rf {self.conf_path};" \
            f"cp {self.conf_path}_testbak {self.conf_path};" \
            f"rm -rf {self.conf_path}_testbak"
        self.log.info(shell_cmd)
        result = self.db_primary_user_node.sh(shell_cmd).result()
        self.log.info(result)

        self.log.info('--------还原集群-------')
        self.comshsta[0].buildStandby('-M standby')
        result = self.comshsta[0].exec_refresh_conf()
        self.log.info(result)

        self.log.info('-----------重启数据库-----------')
        result = self.commonshpri.stopDbCluster()
        self.log.info(result)
        result = self.commonshpri.startDbCluster()
        self.log.info(result)
        self.log.info('---Opengauss_Reliability_Dbsys_Case258.py 执行结束-------')